﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using IPC.Communication.Framework.BasicFramework;

namespace IPC.Communication.Framework.Core.Net
{
    public class NetworkAuthenticationServerBase : NetworkServerBase, IDisposable
    {
        private Dictionary<string, string> accounts = new Dictionary<string, string>();

        private SimpleHybirdLock lockLoginAccount = new SimpleHybirdLock();

        private bool disposedValue = false;

        public bool IsUseAccountCertificate
        {
            get;
            set;
        }

        protected override OperateResult SocketAcceptExtraCheck(Socket socket, IPEndPoint endPoint)
        {
            if (IsUseAccountCertificate)
            {
                OperateResult<byte[], byte[]> operateResult = ReceiveAndCheckBytes(socket, 2000);
                if (!operateResult.IsSuccess)
                {
                    return new OperateResult(String.Format("Client login failed[{0}]", endPoint));
                }
                if (BitConverter.ToInt32(operateResult.Content1, 0) != 5)
                {
                    if (base.LogNet != null)
                    {
                        base.LogNet.WriteError(ToString(), StringResources.Language.NetClientAccountTimeout);
                    }
                    if (socket != null)
                    {
                        socket.Close();
                    }
                    return new OperateResult(String.Format("Authentication failed[{0}]", endPoint));
                }
                string[] array = HslProtocol.UnPackStringArrayFromByte(operateResult.Content2);
                string text = CheckAccountLegal(array);
                SendStringAndCheckReceive(socket, (text == "success") ? 1 : 0, new string[1]
			{
				text
			});
                if (text != "success")
                {
                    return new OperateResult(String.Format("Client login failed[{0}]:{1} {2}", endPoint, text, SoftBasic.ArrayFormat(array)));
                }
                if (base.LogNet != null)
                {
                    base.LogNet.WriteDebug(ToString(), String.Format("Account Login:{0} Endpoint:[{1}]", array[0], endPoint));
                }
            }
            return OperateResult.CreateSuccessResult();
        }

        public void AddAccount(string userName, string password)
        {
            if (!string.IsNullOrEmpty(userName))
            {
                lockLoginAccount.Enter();
                if (accounts.ContainsKey(userName))
                {
                    accounts[userName] = password;
                }
                else
                {
                    accounts.Add(userName, password);
                }
                lockLoginAccount.Leave();
            }
        }

        public void DeleteAccount(string userName)
        {
            lockLoginAccount.Enter();
            if (accounts.ContainsKey(userName))
            {
                accounts.Remove(userName);
            }
            lockLoginAccount.Leave();
        }

        private string CheckAccountLegal(string[] infos)
        {
            if (infos != null && infos.Length < 2)
            {
                return "User Name input wrong";
            }
            string text = "";
            lockLoginAccount.Enter();
            text = ((!accounts.ContainsKey(infos[0])) ? "User Name input wrong" : ((!(accounts[infos[0]] != infos[1])) ? "success" : "Password is not corrent"));
            lockLoginAccount.Leave();
            return text;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    ServerClose();
                    if (lockLoginAccount != null)
                    {
                        lockLoginAccount.Dispose();
                    }
                }
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(disposing: true);
        }

        public override string ToString()
        {
            return String.Format("NetworkAuthenticationServerBase[{0}]", base.Port);
        }
    }
}
